﻿using System;
using System.Linq;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Globalization;
using System.Collections.Generic;
using PIT.Labs.SharePoint.Logger;
using PIT.Labs.SharePoint.Extensions;
using System.Text;
using System.IO;
using System.Collections.ObjectModel;
using System.Diagnostics;
using Microsoft.SharePoint.WebPartPages;
using System.Web.Hosting;
using System.Security.Principal;
using System.Threading;
using Microsoft.Web.Administration;
using PIT.Labs.ProjectRepository.WebParts.ListRandomizerWebPart.Features.RandomizerTimerFeature;
using Microsoft.SharePoint.Administration;
using PIT.Labs.SharePoint.Extensions.Helper;

namespace PIT.Labs.ProjectRepository.WebParts.ListRandomizerWebPart.ListRandomizerWebPart
{

    /// <summary>
    /// Sets the rights on randomized items of a certain list to read-only and adds the XsltListViewWebPart of the list.
    /// </summary>
    [ToolboxItemAttribute(false)]
    public class ListRandomizerWebPart : System.Web.UI.WebControls.WebParts.WebPart, IWebEditable
    {
        /// <summary>
        /// The global resources file for the web part.
        /// </summary>
        public const String RESOURCES_FILE = "PIT.Labs.ProjectRepository.WebParts.ListRandomizerWebPart";

        private static readonly Guid jobID = new Guid("0D7FA52E-9BBA-4891-B235-59C79F413E85");

        private Label lblHiddenCountdown = null;
        private Label lblProgressbar = null;

        private Label lblError = null;

        private static SPLogger logger = new SPLogger();

        #region WebPartProperties

        private int _itemsToShowCount = 0;

        /// <summary>
        /// The GUID of the list on which the <see cref="T:PIT.Labs.ProjectRepository.WebParts.ListRandomizerWebPart.ListRandomizerWebPart.ListRandomizerWebPart"/> is applied.
        /// </summary>
        [WebBrowsable(false)]
        [Personalizable(PersonalizationScope.Shared)]
        public Guid ListID { get; set; }

        /// <summary>
        /// The count of how many items should be displayed.
        /// </summary>
        [WebBrowsable]
        [LocalizedWebDisplayName("ITEM_COUNT", RESOURCES_FILE)]
        [LocalizedWebDescription("ITEM_COUNT_TOOL_TIP", RESOURCES_FILE)]
        [LocalizedCategoryAttribute("CONFIGURATION", RESOURCES_FILE)]
        [Personalizable(PersonalizationScope.Shared)]
        public int ItemsToShowCount
        {
            get { return _itemsToShowCount; }
            set
            {
                if (value <= 0)
                    throw new Microsoft.SharePoint.WebPartPages.WebPartPageUserException("Value must be greater than zero.");
                _itemsToShowCount = value;
            }
        }


        #endregion

        /// <summary>
        /// Creates a set of child controls that are contained in this web part.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            //this.ChromeState = PartChromeState.Minimized;
            this.ChromeType = PartChromeType.None;

            this.lblError = new Label();
            this.lblError.Text = String.Empty;
            this.lblError.ForeColor = System.Drawing.Color.Red;

            this.lblHiddenCountdown = new Label();
            this.lblHiddenCountdown.ID = "countdown";
            //this.lblHiddenCountdown.Visible = false;
            this.lblHiddenCountdown.Style.Add("display", "none");

            this.lblProgressbar = new Label();
            this.lblProgressbar.ID = "progressbar";


            if (this.CheckPreconditions())
            {
                this.Randomize();
            }

            this.Controls.Add(this.lblHiddenCountdown);
            this.Controls.Add(this.lblProgressbar);
            this.Controls.Add(new LiteralControl("<br/>"));
            this.Controls.Add(this.lblError);
        }

        /// <summary>
        /// Raises the PreRender event and registers the jquery progressbar.
        /// </summary>
        /// <param name="e">
        /// An <see cref="System.EventArgs"/> object that contains the event data.
        /// </param>
        protected override void OnPreRender(EventArgs e)
        {
            if (this.CheckPreconditions())
            {
                this.GenerateCountdown();
            }
            base.OnPreRender(e);
        }

        private void GenerateCountdown()
        {
            if (this.ListID != null)
            {
                DateTime timerStarted = DateTime.MinValue;
                using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
                {
                    using (SPSite elevatedSite = siteCollection.GetElevatedSite())
                    {
                        using (SPWeb elevatedWeb = elevatedSite.OpenWeb(SPContext.Current.Web.ID))
                        {
                            SPList elevatedList = elevatedWeb.Lists[this.ListID];
                            Guid workItemID = elevatedList.ID;
                            if (elevatedWeb.AllProperties.Contains(workItemID.ToString("D", CultureInfo.InvariantCulture)))
                            {
                                timerStarted = (DateTime)elevatedWeb.AllProperties[workItemID.ToString("D", CultureInfo.InvariantCulture)];
                                foreach (SPJobDefinition job in elevatedWeb.Site.WebApplication.JobDefinitions)
                                {
                                    if (job.Name == RandomizerTimerFeatureEventReceiver.RANDOMIZER_TIMER_NAME)
                                    {
                                        if ((job.LastRunTime - timerStarted) > TimeSpan.FromSeconds(61))
                                        {
                                            timerStarted = DateTime.Now.Add(TimeSpan.FromSeconds(60));
                                        }
                                        else
                                        {
                                            timerStarted = job.LastRunTime;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                if (timerStarted != DateTime.MinValue)
                {
                    double elapsedSeconds = (DateTime.Now - timerStarted).TotalSeconds;
                    int progress = 0;
                    if (elapsedSeconds < 60)
                    {
                        progress = 100 - Convert.ToInt32((elapsedSeconds / 60) * 100) + 5;
                    }

                    ScriptLink.Register(this.Page, "ListRandomizerWebPart/jquery-1.4.4.js", false);
                    ScriptLink.Register(this.Page, "ListRandomizerWebPart/jquery-ui-1.8.18.custom.min.js", false);
                    ScriptLink.Register(this.Page, "ListRandomizerWebPart/Countdown/jquery.countdown.js", false);
                    CssRegistration.Register("/_Layouts/ListRandomizerWebPart/Countdown/jquery.countdown.css");
                    CssRegistration.Register("/_Layouts/ListRandomizerWebPart/css/jquery-ui-1.8.18.custom.css");

                    String script = @"
			<script type=""text/javascript"">
			$(function () {
				var austDay = new Date();
				austDay = new Date(austDay.getFullYear() + 1, 1 - 1, 26);
				//$('#" + this.lblHiddenCountdown.ClientID + @"').countdown({until: austDay});
				$('#" + this.lblProgressbar.ClientID + @"').progressbar({ value: " + progress + @"});
				$('#" + this.lblHiddenCountdown.ClientID + @"').countdown({until: austDay, format: 'HMS', onTick: updateProgressBar});
				//$('#" + this.lblProgressbar.ClientID + @"').progressbar({ value: 100 });
				setTimeout(updateProgressBar, 1000);
			});

			function updateProgressBar(periods) {
				var progress;
				progress = $('#" + this.lblProgressbar.ClientID + @"').progressbar(""option"", ""value"");
				if (progress > 0) {
					$('#" + this.lblProgressbar.ClientID + @"').progressbar(""option"", ""value"", progress - 1.6);
				} else {
					$('#" + this.lblProgressbar.ClientID + @"').text(""" + SPUtility.GetLocalizedString("$Resources:RELOAD_FOR_NEW_ITEMS", ListRandomizerWebPart.RESOURCES_FILE, (uint)CultureInfo.CurrentUICulture.LCID) + @""");
				}
			}

			</script>
";

                    ClientScriptManager cs = Page.ClientScript;
                    if (!cs.IsClientScriptBlockRegistered(this.GetType().AssemblyQualifiedName))
                        cs.RegisterClientScriptBlock(
                            this.GetType(),
                            this.GetType().AssemblyQualifiedName,
                            script);
                }
            }
        }

        private void Randomize()
        {
            SPUser currentUser = SPContext.Current.Web.CurrentUser;
            using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
            {
                using (SPSite elevatedSite = siteCollection.GetElevatedSite())
                {
                    using (SPWeb elevatedWeb = elevatedSite.OpenWeb(SPContext.Current.Web.ID))
                    {
                        SPList elevatedList = elevatedWeb.Lists[this.ListID];
                        Guid workItemID = elevatedList.ID;
                        try
                        {
                            Guid workItem = elevatedSite.AddWorkItem(
                            workItemID, // A unique Guid that identifies this work item.
                            DateTime.UtcNow, // the date and time the item should be processed
                            RandomizerTimerJob.WorkItemID, // WorkItemType Guid - replace with your own Guid
                            elevatedWeb.ID, // A Guid that specifies the Web site that is associated with the work item. 
                            elevatedList.ID, // A Guid that identifies the parent of the work item.
                            ItemsToShowCount, // A 32-bit integer that identifies the list item that is associated with the work item. ABUSED to specify the count.
                            false, // true to set the Web identifier; otherwise, false.
                            Guid.Empty, // The list ID of the item.
                            Guid.Empty, // A Guid used to batch similar operations together 
                            currentUser.ID, // The SPUser id of the user submitting the work item
                            null, // Binary payload - could be used to pass file contents or similar to the timer job 
                            "Randomizing!", // Text payload - available to the timer job during exection 
                            Guid.Empty // A Guid that identifies the processing of the work item
                            );
                            SPLogger logger = new SPLogger();
                            logger.Log(NLog.LogLevel.Info, "Work item added, ID: " + workItemID);

                            elevatedWeb.AllProperties[workItemID.ToString("D", CultureInfo.InvariantCulture)] = DateTime.Now;
                            elevatedWeb.UnsafeUpdate();

                        }
                        catch (System.Data.SqlClient.SqlException sqlEx)
                        {
                            if (sqlEx.ErrorCode == -2146232060 && sqlEx.Number == 2627)
                            {
                                SPLogger logger = new SPLogger();
                                logger.Log(NLog.LogLevel.Info, "Work item already existed, ID: " + workItemID);
                            }
                            else
                                throw;
                        }
                        catch (Exception ex)
                        {
                            SPLogger logger = new SPLogger();
                            logger.Log(NLog.LogLevel.Error, SPUtilityHelper.GetLocalizedString("ERR005", ListRandomizerWebPart.RESOURCES_FILE), ex);
                            throw;
                        }
                    }
                }
            }
        }





        private bool CheckPreconditions()
        {
            bool result = true;
            if (this.ListID == null)
            {
                this.lblError.Text = SPUtilityHelper.GetLocalizedString("ERR003", RESOURCES_FILE);
                result = false;
            }
            else if (this.ListID == Guid.Empty)
            {
                this.lblError.Text = SPUtilityHelper.GetLocalizedString("ERR003", RESOURCES_FILE);
                result = false;
            }
            else if (!SPContext.Current.Web.ContainsList(this.ListID))
            {
                this.lblError.Text = SPUtilityHelper.GetLocalizedString("ERR003", RESOURCES_FILE);
                result = false;
            }
            return result;
        }

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            EditorPart listEditorPart = new ListEditorPart();
            EditorPartCollection addedEditorParts = null;
            try
            {
                List<EditorPart> editors = new List<EditorPart>();
                listEditorPart.ID = this.ID + "_listEditorPart";
                editors.Add(listEditorPart);
                EditorPartCollection existingEditorParts = base.CreateEditorParts();
                addedEditorParts = new EditorPartCollection(existingEditorParts, editors);
            }
            catch (Exception ex)
            {
                listEditorPart.Dispose();
                logger.Log(NLog.LogLevel.Error, SPUtilityHelper.GetLocalizedString("ERR004", RESOURCES_FILE), ex);
                throw;
            }
            return addedEditorParts;
        }




    }




}

